package com.google.code.virtualhockey.vhx.sds

import scala.collection.mutable.Map
import com.google.appengine.api.datastore.ReadPolicy
import com.google.appengine.api.datastore.ImplicitTransactionManagementPolicy

/**
 * Marks an object as being a schema grouping together the STMetaData objects
 * of persistable entities.
 */
trait STSchema {
  val entities: List[STMetaData[_]]
  val defaultReadPolicy = new ReadPolicy( ReadPolicy.Consistency.STRONG )
  val defaultTransMgmtPolicy = ImplicitTransactionManagementPolicy.NONE
  val defaultDeadline: Double = 30.0

  private val mapMetaByClass: Map[Class[_], STMetaData[_]] = Map.empty
  private val mapMetaByKind: Map[String, STMetaData[_]] = Map.empty

  /**
   * Returns the STMetaData instance referring to the class referenced by the given SKey.
   */
  def getMetaData[A <: STEntity[A]]( key: SKey[A] ): STMetaData[A] = getMetaData( key.cls )

  /**
   * Returns the STMetaData instance referring to the given class.
   */
  def getMetaData[A <: STEntity[A]]( cls: Class[A] ): STMetaData[A] = {
    if ( mapMetaByClass.isEmpty ) {
      for ( meta <- entities )
        mapMetaByClass.put( meta.cls, meta )
    }

    mapMetaByClass.get( cls ).asInstanceOf[STMetaData[A]]
  }

  /**
   * Returns the STMetaData instance that describes the given GAE kind.
   */
  def getMetaData[A <: STEntity[A]]( kind: String ): STMetaData[A] = {
    if ( mapMetaByKind.isEmpty ) {
      for ( meta <- entities )
        mapMetaByKind.put( meta.kind, meta )
    }

    mapMetaByKind.get( kind ).asInstanceOf[STMetaData[A]]
  }
}